package com.wd.nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.wd.command.BaseCommandObject;
import com.wd.command.Command;
import com.wd.entity.server.IServerEntity;
import com.wd.entity.user.UserInfoEntity;
import com.wd.nio.handler.IoHandlerAdapter;
import com.wd.util.ArrayList;
import com.wd.util.ConsoleTable;

/**
 * @date : 2012-9-26, 14:04:36
 * @author: long
 * @email :108232706
 * @qq.com
 * @description: SessionMgr类
 */
public abstract class SessionMgr {

	private ArrayList<SessionObject> freeList = null;
	private ArrayList<SessionObject> useList = null;
	//	private BlockingQueue<SessionObject> userQueue;
	private NioSocketAcceptor acceptor = null;
	private boolean isStarted;
	private int maxCount;
	// private final int warnCount = 2;
	private final Object gate = new Object();
	private Thread acceptThread = null;
	private short acceptStatus = 0;
	private Thread serviceThread = null;
	private short serviceStatus = 0;
	private boolean isAccept;
	private boolean isService;
	private boolean isInit;
	private final IoHandlerAdapter handler;// = new IoHandlerAdapter();
	private final long SELECT_TIMEOUT = 1000L;
	public BaseCommandObject command;
	protected static final Logger logger = LoggerFactory.getLogger(SessionMgr.class);
	private Thread callMainProcessThread;

	// private static String configPath =
	// "E:/work/gameserver/src/main/resources/config/config.properties";
	public SessionMgr(IoHandlerAdapter _handler) {
		handler = _handler;
		command = new BaseCommandObject();
	}

	/** 只负责接受新来的用户，当人数已满，就空循环 */
	private void accept() {
		//		String userIpAddress;
		try {
			while (isAccept) {
				if (acceptStatus == 0) {
					try {
						if (acceptor == null || !acceptor.isStarted())
							break;
						SocketChannel socketChannel = acceptor.getServerChannel().accept();
						// 此处会返回空
						// if (socketChannel == null) {
						// try {
						// Thread.sleep(3000);
						// } catch (InterruptedException e) {
						// e.printStackTrace();
						// }
						// continue;
						// }
						//						userIpAddress = String.format("[Accept]接收到客户连接，来自:%s :%s", socketChannel.socket().getInetAddress(), socketChannel.socket().getPort());
						socketChannel.configureBlocking(false);
						// 检查当前在线人数
						if (maxCount - useList.size() <= 0) {
							socketChannel.close();
							logger.info(String.format("%s%s[Accept]用户连接已达到最大MaxCount:%s,已经关闭此连接！", "", System.getProperty("line.separator"), maxCount));
							continue;
						}
						// 锁住,加锁
						synchronized (gate) {
							acceptor.getSelector().wakeup();
							//							socketChannel.register(acceptor.getSelector(), SelectionKey.OP_READ | SelectionKey.OP_WRITE, freeList.get(0));
							freeList.get(0).sessionKey = socketChannel.register(acceptor.getSelector(), SelectionKey.OP_READ, freeList.get(0));
						}
						freeList.get(0).setChannel(socketChannel);
						freeList.get(0).connectedTime = System.currentTimeMillis();
						GameData.ONLINECOUNT.incrementAndGet();
						//						logger.info(userIpAddress);
						this.handler.sessionCreated(freeList.get(0));
						// freeList.get(0).setHandler(this.handler);
						useList.add(freeList.remove(0));
						// logger.info(String.format("%s%s[Accept]当前在线人数:%s",
						// userIpAddress, System.getProperty("line.separator"),
						// GameData.ONLINECOUNT.incrementAndGet()));
						if (maxCount - useList.size() <= GameData.SERVER.SessionWarnCount) {
							logger.info(String.format("[Accept]用户连接已经小于警告的%s人，当前在线:%s,请检查maxcount:%s设置！", GameData.SERVER.SessionWarnCount, useList.size(), maxCount));
							continue;
						}

					} catch (IOException e) {
						logger.info("[Accept]出现异常", e);
						acceptor.stop();
						break;
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				TimeUnit.MILLISECONDS.sleep(1);
			}
		} catch (InterruptedException e) {
			logger.info("[Accept] while sleep出现中断异常", e);
			Thread.currentThread().interrupt();
		}

	}

	public void printThreadPoolCurrentStatus() {
		ConsoleTable t = new ConsoleTable(5, true);
		t.appendRow();
		t.appendColum("序号").appendColum("线程id").appendColum("isInterrupted").appendColum("isAlive").appendColum("isDaemon");
		t.appendRow();
		t.appendColum(1).appendColum(acceptThread.getName()).appendColum(acceptThread.isInterrupted()).appendColum(acceptThread.isAlive()).appendColum(acceptThread.isDaemon());

		t.appendRow();
		t.appendColum(2).appendColum(serviceThread.getName()).appendColum(serviceThread.isInterrupted()).appendColum(serviceThread.isAlive()).appendColum(serviceThread.isDaemon());

		logger.info(String.format("%s%s%s", "==============SessionMgr Thread Current Status=============", System.getProperty("line.separator"), t.toString()));
	}

	protected abstract BaseCommandObject getFreeCommand();

	// int roomlistRquestCount = 0;

	/**
	 * 提取一个包
	 * 
	 * @param sessionObj
	 * @return
	 */
	private BaseCommandObject getPacketData(SessionObject sessionObj) {
		// 相当于fireMessageReceived接受到，只是这里是读写线程之外的线程操作
		if (!sessionObj.getHasReceiveData().get()) {
			return null;
		}
		// 接收数据的完整包
		// DataPacket dataPacket = null;
		ByteBuffer recvBuffer = sessionObj.getRecvBuffer();
		boolean remain = false;
		BaseCommandObject command = null;
		synchronized (recvBuffer) {
			// 长度不够
			if (recvBuffer.position() < 22) {
				return null;
			}
			int oldposition = recvBuffer.position();
			recvBuffer.flip();
			int remainLength = recvBuffer.remaining();
			int head = recvBuffer.getInt();
			if (head != 29099) {
				recvBuffer.position(0);
				recvBuffer.clear();// 本包出现问题，清空缓冲区，也可以断线处理
				sessionObj.setStatus(GameData.DISCONNECT);
				sessionObj.cmdStatus[5] = 0;
				printByteBufferInfo("[SessionMgr]本包出现问题 getPacketData>> RecvBuffer", recvBuffer);
				throw new IllegalArgumentException("head not 29099");
				//				return null;
			}
			int lenght = recvBuffer.getInt();
			// 一个包超出了缓冲区的大小,limit已经是最大
			if (lenght + 8 > recvBuffer.capacity()) {
				// recvBuffer.position(oldposition);
				// recvBuffer.limit(recvBuffer.capacity());
				recvBuffer.position(0);
				recvBuffer.clear();// 本包出现问题，清空缓冲区，也可以断线处理
				logger.error("session的缓冲区大小不够丢弃这个包");
				return null;
			}
			// 粘包,头4个字节正确，只是包长度没有发完，只有继续等
			if (lenght > recvBuffer.remaining() + 8) {
				printByteBufferInfo("[SessionMgr]包长度没有发完 getPacketData>> RecvBuffer", recvBuffer);
				recvBuffer.position(oldposition);
				recvBuffer.limit(recvBuffer.capacity());
				return null;
			}
			command = getFreeCommand();//ThreadPool.getInstance().getFreeCommand();
			// 线程池资源不够，下次在操作
			if (command == null) {
				recvBuffer.position(oldposition);
				recvBuffer.limit(recvBuffer.capacity());
				//				logger.error("s线程池资源不够，下次在getPacket");
				return null;
			}
			command.setCmd(recvBuffer.getShort());
			// if (command.getCmd() == 2000) {
			// roomlistRquestCount++;
			// logger.info("当前请求房间列表次数:" + roomlistRquestCount);
			// }
			command.sessionObject = sessionObj;
			recvBuffer.position(22);
			command.writeBegin();
			int dataLen = lenght - 22;
			while (dataLen > 0) {
				command.writeByte(recvBuffer.get());
				dataLen--;
			}
			command.writeEnd();
			// printByteBufferInfo("<<getPacketData RecvBuffer", recvBuffer);
			// 提取数据操作
			// dataPacket = new DataPacket();

			// recvBuffer.position(22);
			// byte[] bytes = new byte[lenght - 22];
			// // 将数据部分提取
			// recvBuffer.get(bytes, 0, bytes.length);
			// // dataPacket.writeBegin();
			// dataPacket.writeBytes(bytes);// 将包数据部分存入ByteBuffer
			// dataPacket.writeEnd();

			// 等效写法，分配内存等于包的大小
			// byte[] bytes = new byte[lenght - 22];
			// dataPacket = new DataPacket(cmdId, bytes);
			/*if (lenght > 200) {
				logger.debug(String.format("[Service]接收到数据包,=====in==========in=========>命令:%s %s 总长度:%s 数据:%s", command.getCmd(), CommandSet.getCmdName(command.getCmd()), lenght, "...无限省略..."));
			} else {
				logger.debug(String.format("[Service]接收到数据包,=====in==========in=========>命令:%s %s 总长度:%s 数据:%s", command.getCmd(), CommandSet.getCmdName(command.getCmd()), lenght, "..."));
			}*/
			if (recvBuffer.remaining() > 0) {
				remain = true;
			}
			recvBuffer.compact();// 清除处理过的数据
			// 因为compact已经将
			// position恢复到limit,等待接收数据,limit到最大
			recvBuffer.position(remainLength - lenght);
			recvBuffer.limit(recvBuffer.capacity());
		}
		sessionObj.getHasReceiveData().set(remain);// 在下个取包操作时候，标志位,无包可以省去很多开销

		// if (recvBuffer.position() > 0)
		// printByteBufferInfo("getPacketData>> RecvBuffer", recvBuffer);
		// System.out.println(String.format("get packet:%s",
		// dataPacket.byteToHex()));
		// System.out.println(String.format("get packet:%s",
		// dataPacket.byteToString()));
		return command;
	}

	public boolean isAccept() {
		return isAccept;
	}

	public boolean isService() {
		return isService;
	}

	public boolean isStarted() {
		return isStarted;
	}

	private boolean isTimeOut(SessionObject session, TimeUnit unit, long timeOut) {
		// long curTime = System.currentTimeMillis();
		// long span = curTime - session.connectedTime;
		// long timeoutspan = TimeUnit.MILLISECONDS.convert(timeOut, unit);
		// String spanformat = TimeWatch.getTime(timeoutspan);
		// spanformat = TimeWatch.getTime(span);
		if (System.currentTimeMillis() - session.connectedTime > TimeUnit.MILLISECONDS.convert(timeOut, unit)) {
			logger.info("在线超过:" + timeOut + unit);
			return true;
		}
		return false;
	}

	/** 外面不停调用的主程序 */
	public void MainProcess() {
		// if (true)
		// return;
		SessionObject temp;
		// List<PBMessage> data;
		BaseCommandObject dataPacket;
		int size = useList.size();
		for (int i = 0; i < size; i++) {
			temp = useList.get(i);
			// 将数据拷贝
			//			synchronized (temp.getRecvBuffer()) {
			switch (temp.getStatus()) {
			case GameData.WAITINGCHECKUSER:// 0:// wait:usename password
				// if (isTimeOut(temp, TimeUnit.SECONDS, 5)) {
				// destory(temp);
				// logger.error("WAITINGCHECKUSER玩家超时,系统断线处理");
				// i--;
				// continue;
				// }
				// 等待接受账号密码
				// if (PacketLogin(temp)) // 只接受账号密码的cmd，如果有别的数据，则异常，直接断线
				// List<PBMessage> data = PacketCMD(temp, 1);
				if (temp.cmdStatus[0] == 0) {
					// dataPacket = getPacketData(temp);
					OnConnect(temp, null); // 告诉外界请验证这个账号密码，但是不能在这个函数里面做数据库操作
					// if (收到账号密码) {
					temp.setStatus(1);
					temp.cmdStatus[0] = 1;
				}
				break;
			case GameData.WAITINGCHECKSUCC:// 1:验证账号
				//				if (isTimeOut(temp, TimeUnit.MINUTES, 10)) {
				//					destory(temp);
				//					logger.error("WAITINGCHECKSUCC玩家超时,一直没有验证或通过验证,系统断线处理");
				//					i--;
				//					continue;
				//				}
				if (temp.cmdStatus[1] == 0) {
					dataPacket = getPacketData(temp);
					OnCheck(temp, dataPacket); // 等待成功
				}
				break;
			case GameData.CHECKUSERSUCC:// 2:// 确认成功
				if (temp.cmdStatus[2] == 0) {
					// 因为这里不需要验证包，取包了会影响后面的第一个oncommand命令，根据实际情况，这里只是告诉外面
					// dataPacket = getPacketData(temp);
					OnCheckSuss(temp, null); // 确认成功，玩家进入
					temp.cmdStatus[2] = 1;
				}
				break;
			case GameData.READYGAME:// 3:// Ready
				// while (true) {
				// short cmd = 0;
				// if (cmd <= 0) {
				// break;
				// }
				dataPacket = getPacketData(temp);
				OnCommand(temp, dataPacket); // 告诉外界有一个消息数据过来，自己处理

				// 每次从读缓冲区发出一个包，并删除掉
				// List<PBMessage> data = PacketCMD(temp, 1);
				// OnCommand(temp, data);// 告诉外界有一个消息数据过来，自己处理
				// }
				break;
			case GameData.NOTRECEIVEDATA:// 4:// 特殊状态，没短线，但是不收数据，只等她自己断线
				break;
			case GameData.DISCONNECT:// 5:// 断线处理
				// 释放资源,更改状态
				// OnDisconncet(temp,data.get(0).getCode(),data.get(0).getBytes());
				// if (temp.close()) {
				if (temp.cmdStatus[5] == 0) {
					this.remove(temp);
					i--;
					size--;
					// dataPacket = getPacketData(temp);
					OnDisconncet(temp, null);// 调用虚函数，告诉外界，这个人离开啦
					temp.cmdStatus[5] = 1;
				}
				// }
				break;
			}
			//			}
		}
	}

	public abstract void OnCheck(SessionObject sessionObj, BaseCommandObject command);

	public abstract void OnCheckSuss(SessionObject sessionObj, BaseCommandObject command);

	public abstract void OnCommand(SessionObject sessionObj, BaseCommandObject command);

	public abstract void OnConnect(SessionObject sessionObj, BaseCommandObject command);

	public abstract void OnDisconncet(SessionObject sessionObj, BaseCommandObject command);

	public abstract void OnWaitCheck(SessionObject sessionObj, BaseCommandObject command);

	private void printByteBuffer(String msg, int position, int length, ByteBuffer byteBuffer) {
		if (length < 300) {
			// 转成16进制字符串
			if (byteBuffer == null)
				return;
			StringBuilder tempStr = new StringBuilder("[");
			int oldpositon = byteBuffer.position();
			String value;
			while (byteBuffer.remaining() > 0) {
				value = Integer.toHexString(byteBuffer.get() & 0Xff);
				tempStr.append(value.length() > 1 ? value : String.format("0%s", value)).append(",");
				if (byteBuffer.position() == 22) {
					tempStr.append("[");
				}
			}
			tempStr.append("]]");
			byteBuffer.position(oldpositon);
			logger.debug(String.format("%s[length:%s content:%s]", msg, length, tempStr.toString().toUpperCase()));
			tempStr = null;
		} else {
			logger.debug(String.format("%s[length:%s content:%s]", msg, length, "..."));
			msg = null;
		}
	}

	/**
	 * 接受数据
	 * 
	 * @param key
	 * @throws IOException
	 */
	private boolean receive(SelectionKey key) throws IOException {
		SessionObject sessionObj = (SessionObject) key.attachment();
		// 接收数据，可以从key中获得
		int num = 0;
		synchronized (sessionObj.getRecvBuffer()) {
			//			ByteBuffer tempBuffer = sessionObj.getRecvBuffer();
			// logger.info("接收数据前，接收缓冲区前：remaining:" + tempBuffer.remaining() +
			// " position :" + tempBuffer.position() + " limit:" +
			// tempBuffer.limit());
			num = ((SocketChannel) key.channel()).read(sessionObj.getRecvBuffer());
			// if (sessionObj.getRecvBuffer().position() > 0)
			// printByteBufferInfo("接收数据后 RecvBuffer", tempBuffer);
			sessionObj.getHasReceiveData().set(true);
		}
		if (num == -1) {
			this.closeSessionKey(key);
			return false;
			// throw new IOException("user have close!");
		}
		return true;
	}

	private void printByteBufferInfo(String msg, ByteBuffer tempBuffer) {
		logger.info(String.format("%s remaining:%s position:%s limit:%s", msg, tempBuffer.remaining(), tempBuffer.position(), tempBuffer.limit()));
	}

	/**
	 * 发送数据
	 * 
	 * @param key
	 * @throws IOException
	 */
	private void send(SelectionKey key) throws IOException {
		SessionObject sessionObj = (SessionObject) key.attachment();
		if (!sessionObj.getHasSendData().get()) {
			return;
		}
		// 接收数据，可以从key中获得
		synchronized (sessionObj.getSendBuffer()) {
			// boolean senddata = false;
			//			ByteBuffer tempBuffer = sessionObj.getSendBuffer();
			sessionObj.getSendBuffer().flip();
			// logger.debug("有数据发" + sessionObj.getSendBuffer().remaining());
			if (sessionObj.remaining() > 0) {
				// senddata = true;
				//				short cmd = tempBuffer.getShort(8);
				//				if (cmd == 2000) {
				//					outCmdCount++;
				//					logger.info("发出房间列表个数:" + outCmdCount);
				//				}
				//				this.printByteBuffer(String.format("[service]send=====out=>==>====out===>=>> cmd:%s %s", cmd, CommandSet.getCmdName(cmd)), 0, tempBuffer.remaining(), tempBuffer);
				/*int num = */((SocketChannel) key.channel()).write(sessionObj.getSendBuffer());
				// 一个完整包长度不够，设置没有数据
				if (sessionObj.remaining() <= 0) {
					sessionObj.getHasSendData().set(false);
				}
				sessionObj.getSendBuffer().compact();
			} else {
				sessionObj.getHasSendData().set(false);
			}
			// 将limit，position位置换一下
			// sessionObj.getSendBuffer().position(sessionObj.getSendBuffer().limit());
			// sessionObj.getSendBuffer().limit(sessionObj.getSendBuffer().capacity());
		}

	}

	private boolean SendData(SessionObject sessionObj, byte[] bytes, short cmdId) {
		ByteBuffer sendBuffer = sessionObj.getSendBuffer();
		synchronized (sendBuffer) {
			sendBuffer.putInt(29099);
			sendBuffer.putInt(bytes.length + 22);// length
			sendBuffer.putShort(cmdId);// cmd
			sendBuffer.putInt(1);// temp1
			sendBuffer.putInt(2);// temp2
			sendBuffer.putInt(3);// temp3
			sendBuffer.put(bytes);
		}
		return true;
	}

	//	SelectionKey key = null;
	/** 做数据收发 */
	private void service0() {
		logger.info(String.format("[service]接收读取socket服务开始运行"));
		Set<SelectionKey> readyKeys;
		Iterator<SelectionKey> it;
		while (isService) {
			//			if (serviceStatus == 0) {
			// 锁住对Selector的操作
			if (acceptor == null || !acceptor.isStarted()) {
				logger.error(String.format("[service]acceptor null or isn't started,break out"));
				break;
			}
			synchronized (gate) {
			}
			int n;
			try {
				n = acceptor.getSelector().select();//SELECT_TIMEOUT
			} catch (IOException e1) {
				logger.error(String.format("[service]acceptor select() error%s ,break out", e1));
				break;// 强制中断，退出
			}
			if (n == 0)
				continue;
			readyKeys = acceptor.getSelector().selectedKeys();
			for (SelectionKey key : readyKeys) {
				try {
					readyKeys.remove(key);
					if (key.isReadable()) {
						if (!receive(key)) {
							continue;
						}
					}
					if (key.isWritable()) {
						send(key);
					}
				} catch (IOException e) {
					closeSessionKey(key);
				}
			}

			//			}
			try {
				TimeUnit.MILLISECONDS.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		logger.error("[service]接收读取socket服务停止运行");
	}

	/** 做数据收发 */
	private void service() {
		GameData.SERVICESTARTTIME = System.currentTimeMillis();
		logger.info("[service]接收读取socket服务开始运行");
		Set<SelectionKey> readyKeys;
		Iterator<SelectionKey> it;
		while (isService) {

			if (serviceStatus == 0) {
				// 锁住对Selector的操作
				if (acceptor == null || !acceptor.isStarted()) {
					logger.error(String.format("[service]acceptor null or isn't started,break out"));
					break;
				}
				synchronized (gate) {
				}
				// logger.info("service: waiting for connecting!");
				int n;
				try {
					n = acceptor.getSelector().select();
				} catch (IOException e1) {
					logger.error(String.format("[service]acceptor select() error%s ,break out", e1));
					break;// 强制中断，退出
				}
				if (n == 0)
					continue;
				//				readyKeys = null;
				//				it = null;
				readyKeys = acceptor.getSelector().selectedKeys();
				it = readyKeys.iterator();
				SelectionKey key = null;
				while (it.hasNext()) {
					try {
						key = it.next();
						it.remove();
						//						if (((SessionObject) key.attachment()).getStatus() == GameData.DISCONNECT)
						//							continue;
						// sessionObj.cmdStatus[5]
						if (key.isReadable()) {
							if (!receive(key)) {
								// 因为读数据发生异常，key已被取消
								//								it = null;
								continue;
							}
						}
						//						if (key.isWritable()) {
						//							send(key);
						//						}
						//						if (!key.isValid()) {
						//							closeSessionKey(key);
						//						}
						//						it = null;
					} catch (IOException e) {
						closeSessionKey(key);
					}
				}// #while
			}
			try {
				TimeUnit.MILLISECONDS.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		logger.error("[service]接收读取socket服务停止运行");
	}

	private void closeSessionKey(SelectionKey key) {
		// 如果发生异常，取消该事件
		try {
			// 如果发生异常，取消该事件
			if (key != null) {
				SessionObject sessionObj = (SessionObject) key.attachment();
				sessionObj.setStatus(GameData.DISCONNECT);
				sessionObj.cmdStatus[5] = 0;
				sessionObj.sessionKey = null;
				// this.remove(sessionObj);
				// 使这个SelectionKey失效,
				// 使得Selector不再监控这个SelectionKey感兴趣的事件
				key.cancel();
				// 在读写服务里，不做任何逻辑操作，全部由外面线程去实现，所以移到handler里 key.cancel();
				// key.channel().close(); // 关闭与这个SelectionKey关联的SocketChannel				
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}

	}

	/**
	 * 移除一个session，同时给外面注册的handler事件
	 * 
	 * @param session
	 * @return
	 */
	boolean remove(SessionObject session) {
		destory(session);
		try {
			this.handler.sessionClosed(session);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("移除session error", e);
		}
		return true;
	}

	/**
	 * 关闭key，channel置空，游戏过程状态恢复成初始
	 * 
	 * @param session
	 */
	private void destory(SessionObject session) {
		SelectionKey key = session.sessionKey;
		if (key != null) {
			key.cancel();
		}
		session.sessionKey = null;
		SocketChannel channel = session.getChannel();
		if (channel != null) {
			try {
				channel.close();
			} catch (IOException e) {
				try {
					session.getHandler().exceptionCaught(session, e);
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
			session.setChannel(null);
		}
		for (int j = 0; j < 5; j++) {
			session.cmdStatus[j] = 0;
		}
		session.setStatus(0);
		useList.remove(session);
		freeList.add(session);
		// RoomMgr.outGame(session);
		// UserMgr.I().loginOff(session);
		GameData.ONLINECOUNT.decrementAndGet();
	}

	public void setAccept(boolean isAccept) {
		this.isAccept = isAccept;
	}

	public void setService(boolean isService) {
		this.isService = isService;
	}

	public void setStarted(boolean isStarted) {
		this.isStarted = isStarted;
	}

	public boolean initComponent(boolean initResult, String componentName) {
		if (!initResult)
			logger.error("[SessionMgr]错误:" + componentName);
		else {
			logger.info("[SessionMgr]加载完成!" + componentName);
		}
		return initResult;
	}

	/**
	 * 实例化基础服务器信息
	 * 
	 * @return
	 */
	protected abstract IServerEntity createNewServer();

	/**
	 * 服务器端口,线程数，信息初始化
	 * 
	 * @return
	 */
	protected abstract boolean initServer();

	protected abstract boolean initCommandSet();

	protected abstract boolean startThreadPool();

	// public boolean start(int _port, int _sessionMaxCount, int cmdThreadCount,
	// int cmdQueueCount) throws Throwable {
	public boolean start() throws Throwable {
		long start = System.currentTimeMillis();// System.nanoTime();
		if (!isStarted()) {
			GameData.SERVER = createNewServer();
			if (!initComponent(initServer(), "服务器参数GameData.SERVER.初始化")) {
				return false;
			}
			if (GameData.SERVER == null || GameData.SERVER.Port == 0) {
				logger.error("实例化具体的基础服务器失败！");
				return false;
			}

			if (!initComponent(initCommandSet(), "commandSet初始化")) {
				return false;
			}
			if (!initComponent(startThreadPool(), "线程池初始化")) {
				return false;
			}
			try {
				acceptor = new NioSocketAcceptor();
			} catch (IOException ex) {

				return false;
			}
			if (!acceptor.start(GameData.SERVER.Port)) {
				logger.info("[SessionMgr] NioSocketAcceptor启动失败");
				return false;
			}
			maxCount = GameData.SERVER.SessionMaxCount;
			if (!isInit) {
				init();
			}
			// 外面暂停了，需要继续
			acceptStatus = 0;
			serviceStatus = 0;
			logger.info("[SessionMgr][%s] 服务器启动成功，端口:" + GameData.SERVER.Port + " 最大允许连接:" + maxCount);
			isStarted = true;
			//启动MainProcess
			callMainProcessThread = new Thread(new Runnable() {
				public void run() {
					while (true) {
						try {
							MainProcess();
						} catch (Throwable e) {
							e.printStackTrace();
						}
						try {
							TimeUnit.MILLISECONDS.sleep(1);
						} catch (InterruptedException e) {
							logger.info("MainProcess InterruptedException了");
						}
					}
				}
			});
			callMainProcessThread.setName("CallMainProcess");
			callMainProcessThread.start();
		}

		long duration = System.currentTimeMillis() - start;
		logger.info("[SessionMgr][%s] 启动消耗 " + duration + "毫秒时间");
		return true;
	}

	protected abstract UserInfoEntity createUserInfoEntity();

	private void init() {
		freeList = new ArrayList<SessionObject>("SessionMgr_freeList", maxCount, false, false);
		useList = new ArrayList<SessionObject>("SessionMgr_useList", maxCount, false, false);
		// userQueue = new ArrayBlockingQueue<SessionObject>(maxCount);
		SessionObject sessionObject;
		for (int i = 0; i < maxCount; i++) {
			sessionObject = new SessionObject(this, createUserInfoEntity());
			// 设置了处理事件的handler
			sessionObject.setHandler(this.handler);
			freeList.add(sessionObject);
			// userQueue.offer(sessionObject);
		}
		setStarted(true);
		// 接收新连接线程
		acceptThread = new Thread("acceptThread") {
			@Override
			public void run() {
				isAccept = true;
				accept();
			}
		};
		// acceptThread.setDaemon(true);
		acceptThread.start();
		// 处理读取数据，发数据的线程
		serviceThread = new Thread("serviceThread") {
			@Override
			public void run() {
				isService = true;
				service();
			}
		};
		serviceThread.start();
		isInit = true;
	}

	//	public SessionObject getFreeSessionObject() throws InterruptedException {
	//		logger.debug(userQueue.size());
	//		return userQueue.take();
	//	}
	//
	//	public void freeSessionObject(SessionObject sessionObject) throws InterruptedException {
	//		logger.debug("sessionObject Close and free");
	//		userQueue.put(sessionObject);
	//	}

	protected abstract void threadPoolExit();

	public void exitThread() {
		isAccept = false;
		isService = false;
		threadPoolExit();
		//		ThreadPool.getInstance().exitThread();
	}

	protected abstract void threadPoolPause();

	protected abstract void threadPoolStop();

	/**
	 * 停止所有的服务
	 * 
	 * @return
	 */
	public boolean stop(boolean realStop) {
		// 停止命令线程池
		if (!realStop) {
			threadPoolPause();
			//			ThreadPool.getInstance().Pause();
			logger.info("[SessionMgr] ThreadPool服务暂停!");
			acceptStatus = 1;
			serviceStatus = 1;
			logger.info("[SessionMgr] Service,Accept服务状态暂停!");
		} else {
			threadPoolStop();
			//			ThreadPool.getInstance().stop();
			logger.info("[SessionMgr][ ThreadPool服务停止!");
			isAccept = false;
			isService = false;
			logger.info("[SessionMgr]Service,Accept服务状态停止!");
		}

		// TimerMgr.shutdown();// 停止定时器线程池
		// TimerPool.stop();
		// DBPoolMgr.closePools(); // 关闭数据库连接池
		// SessionObject temp;
		if (useList != null) {
			for (int i = 0; i < useList.size(); i++) {
				// temp = useList.get(i);
				this.remove(useList.get(i));
			}
		}
		clearAllUserList();
		//		UserMgr.I().onlineUserMap.clear();
		//		UserMgr.I().onlineUserList.clear();
		if (acceptor.stop()) {
			logger.info("[SessionMgr]NioSocketAcceptor网络服务停止成功!");
		} else {
			logger.info("[SessionMgr]NioSocketAcceptor网络服务停止失败，请检查日志!");
		}
		setStarted(false);
		return true;
	}

	protected abstract void clearAllUserList();

	public int getUseListSize() {
		return useList.size();
	}

	public int getFreeListSize() {
		return freeList.size();
	}

	public abstract Command getCommand(short cmd);
}
